import { UopService } from '@/core/uop.service';
import { Public, RealIp } from '@/decorators';
import { PayQueryDto, PayRechangeDto } from '@/dtos';
import { BillTypeEnum, UopPaymentTypeEnum } from '@/enums';
import { halt, ok } from '@/utils';
import { InjectQueue } from '@nestjs/bull';
import { Body, Controller, Post } from '@nestjs/common';
import { Queue } from 'bull';
import dayjs from 'dayjs';
import { random } from 'radash';
import { BaseController } from './base.controller';

@Controller('pay')
export class PayController extends BaseController {
  constructor(
    @InjectQueue('bill')
    private readonly billQueue: Queue,
    private readonly uopService: UopService,
  ) {
    super();
  }

  @Public()
  @Post('order')
  async rechange(@Body() { amount }: PayRechangeDto, @RealIp() ip: string) {
    const users = await this.prisma.user.findMany({
      where: { type: 1 },
      take: 10,
    });
    const user = users[random(0, users.length - 1)];
    const type = UopPaymentTypeEnum.ALIPAY;
    const currentTime = dayjs();
    const expireTime = currentTime.add(3, 'minutes');
    const payment = await this.uopService.order({
      type,
      totalAmount: amount * 100,
      expireTime: expireTime.format('YYYY-MM-DD HH:mm:ss'),
      notifyUrl: `${this.uopService.NotifyUrl}/api/wallet/uop/callback`,
      returnUrl: '',
      orderDesc: `充值: ¥${amount}`,
    });
    console.log('充值下单: ', payment);
    if (!payment || !payment?.url) {
      return halt('充值订单信息异常');
    }

    const order = await this.prisma.bill.create({
      data: {
        type: BillTypeEnum.RECHARGE,
        total: Number(amount),
        balance: user.balance,
        frozen: user.frozen,
        ownerId: user.id,
        no: payment.no,
        payType: type,
        payUrl: payment.url,
        expireAt: expireTime.toDate(),
        createdAt: currentTime.toDate(),
        date: new Date(),
      },
    });

    await this.billQueue.add(
      'cancel',
      {
        no: order.no,
      },
      {
        delay: expireTime.diff(dayjs()),
      },
    );
    return ok(payment);
  }

  @Public()
  @Post('query')
  async query(@Body() { no }: PayQueryDto) {
    const type = UopPaymentTypeEnum.ALIPAY;
    const res = await this.uopService.query(no, type);
    return ok({
      no: res.merOrderId,
      errCode: res.errCode,
      payTime: res.payTime,
      status: res.status,
    });
  }
}
